/**
 * Project Looking Glass
 *
 * $RCSfile: JInputComponent.java,v $
 *
 * Copyright (c) 2004-2007, Sun Microsystems, Inc., All Rights Reserved
 *
 * Redistributions in source code form must reproduce the above
 * copyright and this condition.
 *
 * The contents of this file are subject to the GNU General Public
 * License, Version 2 (the "License"); you may not use this file
 * except in compliance with the License. A copy of the License is
 * available at http://www.opensource.org/licenses/gpl-license.php.
 *
 * $Revision: 1.3 $
 * $Date: 2007/05/04 23:11:40 $
 * $State: Exp $
 */
package lionel.input;

import java.util.TreeMap;
import javax.swing.event.EventListenerList;
import net.java.games.input.Component;


/**
 * The base class for all JInput components...
 *
 * @author Krishna Gadepalli
 */
public abstract class JInputComponent {
    protected JInputDevice device;
    protected Component component;

    // The current and last polled value
    protected float previousValue;
    protected float  currentValue;

    protected ID id;

    public static JInputComponent createComponent(JInputDevice device, Component component) {
	Component.Identifier cid = component.getIdentifier();

	if (cid instanceof Component.Identifier.Axis)
	    return new AxisComponent(device, component);

	else if (cid instanceof Component.Identifier.Button)
	    return new ButtonComponent(device, component);

	else if (cid instanceof Component.Identifier.Key)
	    return new ButtonComponent(device, component);

	// should not happen...
	return null;
    }

    public JInputComponent(JInputDevice device, Component component) {

	if ((id = ID.get(component.getIdentifier())) == null)
	    throw new RuntimeException("Invalid component identifier: " + component.getIdentifier());

	this.device = device;
	this.component = component;
	currentValue = previousValue = component.getPollData();
    }

    /**
     * Save the last value from the component and then get the latest value
     */
    public void update() {
	previousValue = currentValue;
	 currentValue = component.getPollData();
    }

    public String toString() {
	return device.getName() + ":" + component.getName() + "=" + currentValue;
    }

    public ID getID() {
	return id;
    }

    public boolean isRelative() {
	return component.isRelative();
    }

    public boolean isAbsolute() {
	return !component.isRelative();
    }

    public String getName() {
	return component.getName();
    }

    public JInputDevice getDevice() {
	return device;
    }

    public float getValue() {
	return currentValue;
    }

    public abstract void sendEvent(EventListenerList listenerList);

    public enum POV {
	   OFF, CENTER, LEFT, RIGHT, UP, UP_RIGHT, UP_LEFT,
	   DOWN, DOWN_LEFT, DOWN_RIGHT;
    };

    public POV getPOVValue() {
	return getPOVValue(currentValue);
    }

    public POV getPOVValue(float value) {

	      if (value == Component.POV.UP	   )  { return POV.UP;	       }
	 else if (value == Component.POV.UP_RIGHT  )  { return POV.UP_RIGHT;   }
	 else if (value == Component.POV.UP_LEFT   )  { return POV.UP_LEFT;    }
	 else if (value == Component.POV.DOWN      )  { return POV.DOWN;       }
	 else if (value == Component.POV.DOWN_RIGHT)  { return POV.DOWN_RIGHT; }
	 else if (value == Component.POV.DOWN_LEFT )  { return POV.DOWN_LEFT;  }
	 else if (value == Component.POV.RIGHT     )  { return POV.RIGHT;      }
	 else if (value == Component.POV.LEFT      )  { return POV.LEFT;       }

	 return POV.CENTER;
    }

    /**
     * It is hard handling the Identifiers in JInput defined as strings...
     */
    public enum ID {
	AXIS_X			(Component.Identifier.Axis.X),
	AXIS_Y			(Component.Identifier.Axis.Y),
	AXIS_Z			(Component.Identifier.Axis.Z),
	AXIS_RX			(Component.Identifier.Axis.RX),
	AXIS_RY			(Component.Identifier.Axis.RY),
	AXIS_RZ			(Component.Identifier.Axis.RZ),
	AXIS_SLIDER		(Component.Identifier.Axis.SLIDER),
	AXIS_SLIDER_ACCELERATION(Component.Identifier.Axis.SLIDER_ACCELERATION),
	AXIS_SLIDER_FORCE	(Component.Identifier.Axis.SLIDER_FORCE),
	AXIS_SLIDER_VELOCITY	(Component.Identifier.Axis.SLIDER_VELOCITY),
	AXIS_X_ACCELERATION	(Component.Identifier.Axis.X_ACCELERATION),
	AXIS_X_FORCE		(Component.Identifier.Axis.X_FORCE),
	AXIS_X_VELOCITY		(Component.Identifier.Axis.X_VELOCITY),
	AXIS_Y_ACCELERATION	(Component.Identifier.Axis.Y_ACCELERATION),
	AXIS_Y_FORCE		(Component.Identifier.Axis.Y_FORCE),
	AXIS_Y_VELOCITY		(Component.Identifier.Axis.Y_VELOCITY),
	AXIS_Z_ACCELERATION	(Component.Identifier.Axis.Z_ACCELERATION),
	AXIS_Z_FORCE		(Component.Identifier.Axis.Z_FORCE),
	AXIS_Z_VELOCITY		(Component.Identifier.Axis.Z_VELOCITY),
	AXIS_RX_ACCELERATION	(Component.Identifier.Axis.RX_ACCELERATION),
	AXIS_RX_FORCE		(Component.Identifier.Axis.RX_FORCE),
	AXIS_RX_VELOCITY	(Component.Identifier.Axis.RX_VELOCITY),
	AXIS_RY_ACCELERATION	(Component.Identifier.Axis.RY_ACCELERATION),
	AXIS_RY_FORCE		(Component.Identifier.Axis.RY_FORCE),
	AXIS_RY_VELOCITY	(Component.Identifier.Axis.RY_VELOCITY),
	AXIS_RZ_ACCELERATION	(Component.Identifier.Axis.RZ_ACCELERATION),
	AXIS_RZ_FORCE		(Component.Identifier.Axis.RZ_FORCE),
	AXIS_RZ_VELOCITY	(Component.Identifier.Axis.RZ_VELOCITY),
	AXIS_POV		(Component.Identifier.Axis.POV),
	AXIS_UNKNOWN		(Component.Identifier.Axis.UNKNOWN),
	BUTTON__0		(Component.Identifier.Button._0),
	BUTTON__1		(Component.Identifier.Button._1),
	BUTTON__2		(Component.Identifier.Button._2),
	BUTTON__3		(Component.Identifier.Button._3),
	BUTTON__4		(Component.Identifier.Button._4),
	BUTTON__5		(Component.Identifier.Button._5),
	BUTTON__6		(Component.Identifier.Button._6),
	BUTTON__7		(Component.Identifier.Button._7),
	BUTTON__8		(Component.Identifier.Button._8),
	BUTTON__9		(Component.Identifier.Button._9),
	BUTTON__10		(Component.Identifier.Button._10),
	BUTTON__11		(Component.Identifier.Button._11),
	BUTTON__12		(Component.Identifier.Button._12),
	BUTTON__13		(Component.Identifier.Button._13),
	BUTTON__14		(Component.Identifier.Button._14),
	BUTTON__15		(Component.Identifier.Button._15),
	BUTTON__16		(Component.Identifier.Button._16),
	BUTTON__17		(Component.Identifier.Button._17),
	BUTTON__18		(Component.Identifier.Button._18),
	BUTTON__19		(Component.Identifier.Button._19),
	BUTTON__20		(Component.Identifier.Button._20),
	BUTTON__21		(Component.Identifier.Button._21),
	BUTTON__22		(Component.Identifier.Button._22),
	BUTTON__23		(Component.Identifier.Button._23),
	BUTTON__24		(Component.Identifier.Button._24),
	BUTTON__25		(Component.Identifier.Button._25),
	BUTTON__26		(Component.Identifier.Button._26),
	BUTTON__27		(Component.Identifier.Button._27),
	BUTTON__28		(Component.Identifier.Button._28),
	BUTTON__29		(Component.Identifier.Button._29),
	BUTTON__30		(Component.Identifier.Button._30),
	BUTTON__31		(Component.Identifier.Button._31),
	BUTTON_TRIGGER		(Component.Identifier.Button.TRIGGER),
	BUTTON_THUMB		(Component.Identifier.Button.THUMB),
	BUTTON_THUMB2		(Component.Identifier.Button.THUMB2),
	BUTTON_TOP		(Component.Identifier.Button.TOP),
	BUTTON_TOP2		(Component.Identifier.Button.TOP2),
	BUTTON_PINKIE		(Component.Identifier.Button.PINKIE),
	BUTTON_BASE		(Component.Identifier.Button.BASE),
	BUTTON_BASE2		(Component.Identifier.Button.BASE2),
	BUTTON_BASE3		(Component.Identifier.Button.BASE3),
	BUTTON_BASE4		(Component.Identifier.Button.BASE4),
	BUTTON_BASE5		(Component.Identifier.Button.BASE5),
	BUTTON_BASE6		(Component.Identifier.Button.BASE6),
	BUTTON_DEAD		(Component.Identifier.Button.DEAD),
	BUTTON_A		(Component.Identifier.Button.A),
	BUTTON_B		(Component.Identifier.Button.B),
	BUTTON_C		(Component.Identifier.Button.C),
	BUTTON_X		(Component.Identifier.Button.X),
	BUTTON_Y		(Component.Identifier.Button.Y),
	BUTTON_Z		(Component.Identifier.Button.Z),
	BUTTON_LEFT_THUMB	(Component.Identifier.Button.LEFT_THUMB),
	BUTTON_RIGHT_THUMB	(Component.Identifier.Button.RIGHT_THUMB),
	BUTTON_LEFT_THUMB2	(Component.Identifier.Button.LEFT_THUMB2),
	BUTTON_RIGHT_THUMB2	(Component.Identifier.Button.RIGHT_THUMB2),
	BUTTON_SELECT		(Component.Identifier.Button.SELECT),
	BUTTON_MODE		(Component.Identifier.Button.MODE),
	BUTTON_LEFT_THUMB3	(Component.Identifier.Button.LEFT_THUMB3),
	BUTTON_RIGHT_THUMB3	(Component.Identifier.Button.RIGHT_THUMB3),
	BUTTON_TOOL_PEN		(Component.Identifier.Button.TOOL_PEN),
	BUTTON_TOOL_RUBBER	(Component.Identifier.Button.TOOL_RUBBER),
	BUTTON_TOOL_BRUSH	(Component.Identifier.Button.TOOL_BRUSH),
	BUTTON_TOOL_PENCIL	(Component.Identifier.Button.TOOL_PENCIL),
	BUTTON_TOOL_AIRBRUSH	(Component.Identifier.Button.TOOL_AIRBRUSH),
	BUTTON_TOOL_FINGER	(Component.Identifier.Button.TOOL_FINGER),
	BUTTON_TOOL_MOUSE	(Component.Identifier.Button.TOOL_MOUSE),
	BUTTON_TOOL_LENS	(Component.Identifier.Button.TOOL_LENS),
	BUTTON_TOUCH		(Component.Identifier.Button.TOUCH),
	BUTTON_STYLUS		(Component.Identifier.Button.STYLUS),
	BUTTON_STYLUS2		(Component.Identifier.Button.STYLUS2),
	BUTTON_UNKNOWN		(Component.Identifier.Button.UNKNOWN),
	BUTTON_BACK		(Component.Identifier.Button.BACK),
	BUTTON_EXTRA		(Component.Identifier.Button.EXTRA),
	BUTTON_FORWARD		(Component.Identifier.Button.FORWARD),
	BUTTON_LEFT		(Component.Identifier.Button.LEFT),
	BUTTON_MIDDLE		(Component.Identifier.Button.MIDDLE),
	BUTTON_RIGHT		(Component.Identifier.Button.RIGHT),
	BUTTON_SIDE		(Component.Identifier.Button.SIDE),
	KEY_VOID		(Component.Identifier.Key.VOID),
	KEY_ESCAPE		(Component.Identifier.Key.ESCAPE),
	KEY__1			(Component.Identifier.Key._1),
	KEY__2			(Component.Identifier.Key._2),
	KEY__3			(Component.Identifier.Key._3),
	KEY__4			(Component.Identifier.Key._4),
	KEY__5			(Component.Identifier.Key._5),
	KEY__6			(Component.Identifier.Key._6),
	KEY__7			(Component.Identifier.Key._7),
	KEY__8			(Component.Identifier.Key._8),
	KEY__9			(Component.Identifier.Key._9),
	KEY__0			(Component.Identifier.Key._0),
	KEY_MINUS		(Component.Identifier.Key.MINUS),
	KEY_EQUALS		(Component.Identifier.Key.EQUALS),
	KEY_BACK		(Component.Identifier.Key.BACK),
	KEY_TAB			(Component.Identifier.Key.TAB),
	KEY_Q			(Component.Identifier.Key.Q),
	KEY_W			(Component.Identifier.Key.W),
	KEY_E			(Component.Identifier.Key.E),
	KEY_R			(Component.Identifier.Key.R),
	KEY_T			(Component.Identifier.Key.T),
	KEY_Y			(Component.Identifier.Key.Y),
	KEY_U			(Component.Identifier.Key.U),
	KEY_I			(Component.Identifier.Key.I),
	KEY_O			(Component.Identifier.Key.O),
	KEY_P			(Component.Identifier.Key.P),
	KEY_LBRACKET		(Component.Identifier.Key.LBRACKET),
	KEY_RBRACKET		(Component.Identifier.Key.RBRACKET),
	KEY_RETURN		(Component.Identifier.Key.RETURN),
	KEY_LCONTROL		(Component.Identifier.Key.LCONTROL),
	KEY_A			(Component.Identifier.Key.A),
	KEY_S			(Component.Identifier.Key.S),
	KEY_D			(Component.Identifier.Key.D),
	KEY_F			(Component.Identifier.Key.F),
	KEY_G			(Component.Identifier.Key.G),
	KEY_H			(Component.Identifier.Key.H),
	KEY_J			(Component.Identifier.Key.J),
	KEY_K			(Component.Identifier.Key.K),
	KEY_L			(Component.Identifier.Key.L),
	KEY_SEMICOLON		(Component.Identifier.Key.SEMICOLON),
	KEY_APOSTROPHE		(Component.Identifier.Key.APOSTROPHE),
	KEY_GRAVE		(Component.Identifier.Key.GRAVE),
	KEY_LSHIFT		(Component.Identifier.Key.LSHIFT),
	KEY_BACKSLASH		(Component.Identifier.Key.BACKSLASH),
	KEY_Z			(Component.Identifier.Key.Z),
	KEY_X			(Component.Identifier.Key.X),
	KEY_C			(Component.Identifier.Key.C),
	KEY_V			(Component.Identifier.Key.V),
	KEY_B			(Component.Identifier.Key.B),
	KEY_N			(Component.Identifier.Key.N),
	KEY_M			(Component.Identifier.Key.M),
	KEY_COMMA		(Component.Identifier.Key.COMMA),
	KEY_PERIOD		(Component.Identifier.Key.PERIOD),
	KEY_SLASH		(Component.Identifier.Key.SLASH),
	KEY_RSHIFT		(Component.Identifier.Key.RSHIFT),
	KEY_MULTIPLY		(Component.Identifier.Key.MULTIPLY),
	KEY_LALT		(Component.Identifier.Key.LALT),
	KEY_SPACE		(Component.Identifier.Key.SPACE),
	KEY_CAPITAL		(Component.Identifier.Key.CAPITAL),
	KEY_F1			(Component.Identifier.Key.F1),
	KEY_F2			(Component.Identifier.Key.F2),
	KEY_F3			(Component.Identifier.Key.F3),
	KEY_F4			(Component.Identifier.Key.F4),
	KEY_F5			(Component.Identifier.Key.F5),
	KEY_F6			(Component.Identifier.Key.F6),
	KEY_F7			(Component.Identifier.Key.F7),
	KEY_F8			(Component.Identifier.Key.F8),
	KEY_F9			(Component.Identifier.Key.F9),
	KEY_F10			(Component.Identifier.Key.F10),
	KEY_NUMLOCK		(Component.Identifier.Key.NUMLOCK),
	KEY_SCROLL		(Component.Identifier.Key.SCROLL),
	KEY_NUMPAD7		(Component.Identifier.Key.NUMPAD7),
	KEY_NUMPAD8		(Component.Identifier.Key.NUMPAD8),
	KEY_NUMPAD9		(Component.Identifier.Key.NUMPAD9),
	KEY_SUBTRACT		(Component.Identifier.Key.SUBTRACT),
	KEY_NUMPAD4		(Component.Identifier.Key.NUMPAD4),
	KEY_NUMPAD5		(Component.Identifier.Key.NUMPAD5),
	KEY_NUMPAD6		(Component.Identifier.Key.NUMPAD6),
	KEY_ADD			(Component.Identifier.Key.ADD),
	KEY_NUMPAD1		(Component.Identifier.Key.NUMPAD1),
	KEY_NUMPAD2		(Component.Identifier.Key.NUMPAD2),
	KEY_NUMPAD3		(Component.Identifier.Key.NUMPAD3),
	KEY_NUMPAD0		(Component.Identifier.Key.NUMPAD0),
	KEY_DECIMAL		(Component.Identifier.Key.DECIMAL),
	KEY_F11			(Component.Identifier.Key.F11),
	KEY_F12			(Component.Identifier.Key.F12),
	KEY_F13			(Component.Identifier.Key.F13),
	KEY_F14			(Component.Identifier.Key.F14),
	KEY_F15			(Component.Identifier.Key.F15),
	KEY_KANA		(Component.Identifier.Key.KANA),
	KEY_CONVERT		(Component.Identifier.Key.CONVERT),
	KEY_NOCONVERT		(Component.Identifier.Key.NOCONVERT),
	KEY_YEN			(Component.Identifier.Key.YEN),
	KEY_NUMPADEQUAL		(Component.Identifier.Key.NUMPADEQUAL),
	KEY_CIRCUMFLEX		(Component.Identifier.Key.CIRCUMFLEX),
	KEY_AT			(Component.Identifier.Key.AT),
	KEY_COLON		(Component.Identifier.Key.COLON),
	KEY_UNDERLINE		(Component.Identifier.Key.UNDERLINE),
	KEY_KANJI		(Component.Identifier.Key.KANJI),
	KEY_STOP		(Component.Identifier.Key.STOP),
	KEY_AX			(Component.Identifier.Key.AX),
	KEY_UNLABELED		(Component.Identifier.Key.UNLABELED),
	KEY_NUMPADENTER		(Component.Identifier.Key.NUMPADENTER),
	KEY_RCONTROL		(Component.Identifier.Key.RCONTROL),
	KEY_NUMPADCOMMA		(Component.Identifier.Key.NUMPADCOMMA),
	KEY_DIVIDE		(Component.Identifier.Key.DIVIDE),
	KEY_SYSRQ		(Component.Identifier.Key.SYSRQ),
	KEY_RALT		(Component.Identifier.Key.RALT),
	KEY_PAUSE		(Component.Identifier.Key.PAUSE),
	KEY_HOME		(Component.Identifier.Key.HOME),
	KEY_UP			(Component.Identifier.Key.UP),
	KEY_PAGEUP		(Component.Identifier.Key.PAGEUP),
	KEY_LEFT		(Component.Identifier.Key.LEFT),
	KEY_RIGHT		(Component.Identifier.Key.RIGHT),
	KEY_END			(Component.Identifier.Key.END),
	KEY_DOWN		(Component.Identifier.Key.DOWN),
	KEY_PAGEDOWN		(Component.Identifier.Key.PAGEDOWN),
	KEY_INSERT		(Component.Identifier.Key.INSERT),
	KEY_DELETE		(Component.Identifier.Key.DELETE),
	KEY_LWIN		(Component.Identifier.Key.LWIN),
	KEY_RWIN		(Component.Identifier.Key.RWIN),
	KEY_APPS		(Component.Identifier.Key.APPS),
	KEY_POWER		(Component.Identifier.Key.POWER),
	KEY_SLEEP		(Component.Identifier.Key.SLEEP),
	KEY_UNKNOWN		(Component.Identifier.Key.UNKNOWN);

	Component.Identifier componentID;

	ID(Component.Identifier componentID) {
	    this.componentID = componentID;
	}

	static TreeMap<String, ID> idMap;

	static String getKey(Component.Identifier id) {
	    return id.getClass().getName() + id.getName();
	}

	static {
	    idMap = new TreeMap<String, ID>();
	    for (ID id: ID.values())
		idMap.put(getKey(id.componentID), id);
	}

	static ID get(Component.Identifier id) {
	    return idMap.get(getKey(id));
	}
    }
}
